home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
C and C++
/
Compilers⁄Interps
/
kevoSource
/
image.c
< prev
next >
Wrap
Text File
|
1993-05-09
|
12KB
|
449 lines
/* Kevo -- a prototype-based object-oriented language */
/* (c) Antero Taivalsaari 1991-1993 */
/* Some parts (c) Antero Taivalsaari 1986-1988 */
/* image.c: Image file management & decompilation */
#include "global.h"
/*--------------------------------------------------------------------------*/
/* Image file forward reference resolver operations */
SOLVE* LastRef = NIL;
/* initResolver(): initialize the resolver list */
void initResolver()
{
LastRef = NIL;
}
/* addForwardRef(): add a new name to resolver list */
void addForwardRef(name, location)
char* name;
int* location;
{
SOLVE* newRef = (SOLVE*)mymalloc(sizeof(SOLVE));
#ifdef DEBUG
printf("Adding forward reference: %s\n", name);
#endif
newRef->name = allocStrCpy(name);
newRef->loc = location;
newRef->next = LastRef;
LastRef = newRef;
}
/* resolveRefs(): resolve all the previous references to a name */
int resolveRefs(name, object)
char* name;
int object;
{
SOLVE* thisRef = LastRef;
SOLVE* prevRef = NIL;
SOLVE* tempRef;
int count = 0;
while(thisRef) {
if (strcmp(thisRef->name, name) == 0) {
*thisRef->loc = object;
count++;
#ifdef DEBUG
printf("Resolving forward reference: %s\n", name);
#endif
if (prevRef == NIL) LastRef = thisRef->next;
else prevRef->next = thisRef->next;
tempRef = thisRef;
thisRef = thisRef->next;
free(tempRef->name);
free(tempRef);
}
else {
prevRef = thisRef;
thisRef = thisRef->next;
}
}
return(count);
}
/* resolvedOk(): Are all the forward references already resolved? */
int resolvedOk()
{
if (LastRef == NIL) return(TRUE);
else {
SOLVE* thisRef = LastRef;
SOLVE* tempRef;
while(thisRef) {
fprintf(stderr, "Unresolved reference '%s'.\n", thisRef->name);
tempRef = thisRef;
thisRef = thisRef->next;
free(tempRef->name);
free(tempRef);
}
LastRef = NIL;
return(FALSE);
}
}
/* ---------------------------------------------------------------------------------- */
/* openImage(): open image file */
void openImage(argc, argv)
int argc;
char* argv[];
{
if (argc > 1 ) {
if ((imgfile = fopen(argv[1], "r")) == NIL) {
printf("%s: cannot open image file \"%s\".\n", argv[0], argv[1]);
exit(1);
}
}
else {
if ((imgfile = fopen("kevo.img", "r")) == NIL) {
/* printf("%s: cannot open standard image file \"kevo.img\".\n", argv[0]); */
printf("Cannot find standard image file 'kevo.img'.\nCannot continue. Exiting.\n");
exit(1);
}
}
}
/* readComment: this operation is needed only in 'loadImage()'. */
/* Its purpose is to read text until we encounter two right parentheses. */
void readComment()
{
paren:
while(fgetc(imgfile) != ')');
switch(fgetc(imgfile)) {
case ')': break;
default : goto paren;
}
}
/* loadImage(): load an image file to the system */
/* xxx This code is rather ugly. Rewrite later. */
void loadImage()
{
char command[10];
char name[64];
char input[64];
int number;
PAIR* newPair;
PAIR* pair;
PAIR* prevPair;
OBJECT* object;
int* store;
while(fscanf(imgfile, "%s", command) != EOF) {
if (strcmp(command, "::") == 0) {
if (fscanf(imgfile, "%s %ld", name, &number) == EOF) goto corrupt;
/* xxx we shouldn't limit to 'rootContext' only. Change later. */
/* printf("Defining: %s, number: %ld.\n", name, number); */
newPair = addPair(rootContext, allocStrCpy(name), object = createClosure(number));
(void)resolveRefs(newPair->nfa, (int)newPair->ofa);
store = (int*)object->mfa;
prevPair = rootContext->firstPair;
for ( ; number; number--) {
if (fscanf(imgfile, "%s", input) == EOF) goto corrupt;
if (strcmp(input, "^^") == 0) { /* String literal */
char* ptr;
char ch;
*store++ = (int)oStrLit;
ptr = charbuffer; /* use the shared char buffer (global.c) */
(void)fgetc(imgfile); /* Read the extra blank */
/* Read text until we find two carats */
carat:
while((ch = fgetc(imgfile)) != '^') *ptr++ = ch;
switch(ch = fgetc(imgfile)) {
case '^': *ptr = 0; break;
default : ungetc(ch, imgfile); goto carat;
}
*store++ = (int)allocStrCpy(charbuffer); number--;
/* printf("^^%s^^ ", charbuffer); */
prevPair = rootContext->firstPair;
}
else { /* Not a string literal */
if (strcmp(input, "((") == 0) {
readComment();
number++;
/* printf("Comment "); */
}
else {
char* temp;
char** endPtr = &temp;
int result = strtol(input, endPtr, 0);
if (!**endPtr) {
*store++ = result; /* Number */
prevPair = rootContext->firstPair;
/* printf("%ld ", result); */
}
else {
if (pair = findPairInThis(rootContext, input)) {
*store++ = (int)pair->ofa;
/* printf("%s ", pair->nfa); */
/* If '(=context)', allocate a context */
if (pair->ofa == oContext && prevPair->ofa != oLit) {
/* xxx This must changed when image file loading is implemented in full detail */
fscanf(imgfile, "%s", input); number--;
if (strcmp(input, "DUMMY") == 0)
*store++ = (int)dummyContext;
else *store++ = (int)lowCreateContext();
}
prevPair = pair;
}
else {
addForwardRef(input, store++); /* Add to unresolved */
prevPair = rootContext->firstPair;
/* printf("Unresolved: %s ", input); */
}
}
}
}
}
if (fscanf(imgfile, "%s %lx", command, &number) == EOF) goto corrupt;
if (strcmp(command, ";;") != 0) goto corrupt;
newPair->ffa = number;
/* printf("\nFlag field: %ld\n", number); */
}
else { /* Allow comments outside of definitions, too */
if (strcmp(command, "((") != 0) goto corrupt;
else readComment();
}
}
if (!resolvedOk()) {
printf("Unresolved references in image file.\n");
printf("Cannot continue. Exiting.\n");
exit(1);
}
return;
corrupt:
printf("Image file structure corrupted near \"%s\".\n", name);
printf("Cannot continue. Exiting.\n");
exit(1);
}
/* initVariables(): initialize certain variables defined in image file
/* so that primitive definitions can execute high-level definitions. */
/* In particular, we want to invoke the high-level error routine */
/* from primitives. */
void initVariables()
{
PAIR* pair;
STORE* store;
pair = findPairInThis(rootContext, "SystemRoot");
if (pair && pair->ofa && (store = pair->ofa->mfa)) {
/* 'SystemRoot' should point to 'rootContext'. Therefore, we */
/* free the automatically (by 'loadImage') allocated context */
free(store->pfa);
store->pfa = (int*)rootContext;
/* 'SystemRoot' must be made a full-fledged object */
/* by storing itself to its clone family (which is still empty) */
addToList(rootContext->cloneFamily, pair->ofa);
}
else goto error;
pair = findPairInThis(rootContext, "Root");
if (pair && pair->ofa && (store = pair->ofa->mfa)) {
/* 'Root' should point to 'userContext'. Therefore, we */
/* free the automatically (by 'loadImage') allocated context */
free(store->pfa);
store->pfa = (int*)userContext;
oUserRoot = pair->ofa;
/* 'Root' must be made a full-fledged object */
/* by storing itself to its clone family (which is still empty) */
addToList(userContext->cloneFamily, oUserRoot);
}
else goto error;
/* 'Up', 'firstTask, and 'latestTask' must initially point to the '(user)' task data area */
pair = findPairInThis(rootContext, "(user)");
if (pair && pair->ofa && pair->ofa->mfa)
firstTask = latestTask = up = (TASK**)pair->ofa;
else goto error;
/* 'oBoot' must point to 'boot' */
pair = findPairInThis(rootContext, "boot");
if (pair && pair->ofa && pair->ofa->mfa)
oBoot = pair->ofa;
else goto error;
/* 'oShell' must point to 'shell' */
/* This is needed for the debugger */
pair = findPairInThis(rootContext, "shell");
if (pair && pair->ofa && pair->ofa->mfa)
oShell = pair->ofa;
else goto error;
/* 'oError' must point to vector 'error' */
pair = findPairInThis(rootContext, "error");
if (pair && pair->ofa && pair->ofa->mfa)
oError = pair->ofa;
else {
error:
printf("Certain name(s) could not be found in image file.\n");
printf("Cannot continue. Exiting.\n");
exit(1);
}
}
/* ------------------------------------------------------------------------------- */
/* Decompilation and image file generation */
/* decompile the definition of an object */
void decompile(object)
OBJECT* object;
{
OBJECT** addr = (OBJECT**)object->mfa;
PAIR* thisPair;
PAIR* prevPair = rootContext->firstPair; /* xxx Whichever pair will do */
int count = object->sfa;
ownPrintf(":: ");
if (count) { /* Not a primitive */
if (count > 200) {
ownPrintf("-- This definition is very large: decompiling only first 200 items -- ");
ownCr();
count = 200;
}
for ( ; count > 0; count--, addr++) {
thisPair = findNameBackward(*addr);
if (thisPair) {
if (strcmp(thisPair->nfa, "(\"lit)") == 0) {
if (strcmp(prevPair->nfa, "(lit)") == 0) ownPrintf("\"lit) ");
else {
ownPrintf("^^ %s^^ ", (char*)*++addr);
count--;
}
}
else ownPrintf("%s ", thisPair->nfa);
prevPair = thisPair;
}
else {
thisPair = findTypeForward(*addr);
if (thisPair) {
ownPrintf("%s:", thisPair->nfa);
ownPrintf("%d ", (int)*addr);
}
else ownPrintf("%d ", (int)*addr);
prevPair = rootContext->firstPair; /* Any pair will do */
}
}
}
else { /* Is a primitive */
ownPrintf("(=primitive) %d ", (int)addr);
}
ownPrintf(";;");
thisPair = findNameBackward(object);
if (thisPair && (thisPair->ffa & ImmedFlag)) ownPrintf(" immediate");
if (thisPair && (thisPair->ffa & HiddenFlag)) ownPrintf(" hidden");
ownCr();
}
/* generate an image of the whole system to outfile */
/* (decompile the definitions of all the objects in their definition order) */
/* xxx this needs to be reimplemented later */
void generateImage()
{
/* xxx remove 'rootContext' later */
PAIR* pair = rootContext->firstPair;
while (pair != NIL) {
OBJECT* object = pair->ofa;
OBJECT** addr = (OBJECT**)object->mfa;
PAIR* thisPair;
PAIR* prevPair = rootContext->firstPair; /* Any pair is ok */
int count = object->sfa;
if (count) { /* Not a primitive */
ownPrintf(":: %s ", pair->nfa);
ownPrintf("%d ", count);
for ( ; count--; addr++) {
thisPair = findNameForward(*addr);
if (thisPair) {
if (strcmp(thisPair->nfa, "(\"lit)") == 0) {
if (strcmp(prevPair->nfa, "(lit)") == 0)
ownPrintf("(\"lit) "); /* (lit) ("lit) */
else {
ownPrintf("^^ %s^^ ", (char*)*++addr);
count--;
}
}
else ownPrintf("%s ", thisPair->nfa);
prevPair = thisPair;
}
else {
ownPrintf("%d ", (int)*addr);
prevPair = rootContext->firstPair; /* Any pair is ok */
}
}
ownPrintf(";;");
thisPair = findNameForward(object);
if (thisPair) {
ownPrintf(" %x", thisPair->ffa);
ownCr();
}
}
pair = pair->sfa;
}
}